home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9310.ZIP / 1993-OCT.ZIP / LINKLIST.ASC < prev    next >
Text File  |  1993-09-21  |  33KB  |  1,227 lines

  1. _COMPARING OBJECT-ORIENTED LANGUAGES_
  2. by Michael Floyd
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. C++ Implementation by David Betz (Dr. Dobb's Journal)
  8.  
  9.  
  10. #include <iostream.h>
  11.  
  12. /* any object that will appear in a list must inherit from this class */
  13. class MyListData {
  14. public:
  15.     virtual void Print(void);
  16. };
  17. void MyListData::Print(void)
  18. {
  19.     cout << "No print method!\n";
  20. }
  21. class MyListElement {
  22.      MyListData *data;
  23.      MyListElement *next;
  24. public:
  25.      MyListElement(MyListData *initialData) { data = initialData; next = nil; }
  26.      friend class MyList;
  27. };
  28. class MyList : public MyListData {
  29.     MyListElement *head;
  30.     MyListElement *tail;
  31. public:
  32.     MyList(void) { head = tail = nil; }
  33.     void AddToList(MyListData *data);
  34.     void Print(void);
  35. };
  36. void MyList::AddToList(MyListData *data)
  37. {
  38.     MyListElement *newElement = new MyListElement(data);
  39.     if (head == nil)
  40.         head = tail = newElement;
  41.     else {
  42.         tail->next = newElement;
  43.         tail = newElement;
  44.     }
  45. }
  46. void MyList::Print(void)
  47. {
  48.     MyListElement *element;
  49.     for (element = head; element != nil; element = element->next)
  50.     element->data->Print();
  51. }
  52. class MyNumber : public MyListData {
  53.     int value;
  54. public:
  55.     MyNumber(int initialValue) { value = initialValue; }
  56.     virtual void Print(void);
  57. };
  58. void MyNumber::Print(void)
  59. {
  60.     cout << "Number: " << value << "\n";
  61. }
  62. class MyPoint : public MyListData {
  63.     int x;
  64.     int y;
  65. public:
  66.     MyPoint(int initialX,int initialY) { x = initialX; y = initialY; }
  67.     virtual void Print(void);
  68. };
  69. void MyPoint::Print(void)
  70. {
  71.     cout << "Point: " << x << "," << y << "\n";
  72. }
  73. void main(void)
  74. {
  75.     MyList *list1 = new MyList;
  76.     MyList *list2 = new MyList;
  77.     MyNumber *n1 = new MyNumber(10);
  78.     MyNumber *n2 = new MyNumber(20);
  79.     MyPoint *p1 = new MyPoint(2,3);
  80.     MyPoint *p2 = new MyPoint(4,5);
  81.     /* build the lists */
  82.     list1->AddToList(n1);
  83.     list1->AddToList(n2);
  84.     list1->AddToList(p1);
  85.     list2->AddToList(n2);    /* an object can be in more than one list    */
  86.     list2->AddToList(p1);    /*    at the same time                       */
  87.     list2->AddToList(p2);
  88.     list2->AddToList(list1); /* we can even put a list into another list */
  89.     /* print the lists */
  90.     cout << "list1:\n";
  91.     list1->Print();
  92.     cout << "list2:\n";
  93.     list2->Print();
  94. }
  95.  
  96.  
  97. [LISTING TWO]
  98.  
  99. Objective-C Implementation by Stephen Asbury (Next Computer)
  100.  
  101. #import <stdio.h>
  102. #import <objc/Object.h>/* Include the header for the Root class */
  103.  
  104. @interface LinkedListNode:Object /* declare a node class */
  105. {
  106.     id value;/* a node can store an object of any class as it's  
  107. value */
  108.     id next;
  109. }
  110. - setValue:newValue;
  111. - value;
  112. - setNext:newNext;
  113. - next;
  114. - print;
  115. @end
  116. @implementation LinkedListNode /* implement the node class */
  117. - setValue:newValue {value = newValue; return self;}
  118. - value {return value;}
  119. - setNext:newNext {next = newNext; return self;}
  120. - next {return next;}
  121. - print
  122. {   /* In order to allow any object to be added to the list, we first check
  123.     * to see if the value can print, if so have it print */
  124.     if([value respondsTo:@selector(print)] == YES) [value print];
  125.     return self;
  126. }
  127. @end
  128. @interface LinkedList:Object /* declare a linked list class */
  129. {id tail,head;}
  130. - addObjectToList:theObject;
  131. - print;
  132. @end
  133. @implementation LinkedList /* implement the linked list class */
  134. - init /* refine the init method of the super class */
  135. {
  136.     self = [super init];
  137.     tail = head = nil;
  138.     return self;
  139. }
  140. - addNodeToList:newNode /* private method used only by the object */
  141. {
  142.     if(head == nil)
  143.         head = tail = newNode;
  144.     else{
  145.         [tail setNext:newNode];
  146.         tail = newNode;
  147.     }
  148.     return self;
  149. }
  150. - addObjectToList:theObject
  151. {
  152.     id newNode = [[[LinkedListNode alloc] init]  
  153. setValue:theObject];
  154.     [self addNodeToList:newNode];
  155.     return self;
  156. }
  157. - print
  158. {
  159.     id element;
  160.     for(element = head;element != nil;element = [element next])
  161.         [element print];
  162.     return self;
  163. }
  164. @end
  165. @interface MyNumber:Object /* declare a number class */
  166. {float value;}
  167. - initValue:(float)aValue;
  168. - print;
  169. @end
  170. @implementation MyNumber /* implement the number class */
  171. - initValue:(float)aValue
  172. {
  173.     self = [super init];
  174.     value = aValue;
  175.     return self;
  176. }
  177. - print {printf("Number %f\n",value); return self;}
  178. @end
  179.  
  180. @interface Point:Object /* declare a point class */
  181. {float X,Y;}
  182. - initX:(float)anX y:(float)anY;
  183. - print;
  184. @end
  185. @implementation Point /* implement the point class */
  186. - initX:(float)anX y:(float)anY
  187. {
  188.     self = [super init];
  189.     X = anX;
  190.     Y = anY;
  191.     return self;
  192. }
  193. - print { printf("Point %f , %f\n",X,Y); return self; }
  194. @end
  195. void main(void)
  196. {
  197.     id list1 = [[LinkedList alloc] init];
  198.     id list2 = [[LinkedList alloc] init];
  199.     id number1 = [[MyNumber alloc] initValue:10];
  200.     id number2 = [[MyNumber alloc] initValue:20];
  201.     id point1 = [[Point alloc] initX:2 y:3];
  202.     id point2 = [[Point alloc] initX:4 y:5];
  203.     /* Build the Lists */
  204.     [list1 addObjectToList:number1];
  205.     [list1 addObjectToList:number2];
  206.     [list1 addObjectToList:point1];
  207.     [list2 addObjectToList:number2];/* an object can be in  
  208. multiple list */
  209.     [list2 addObjectToList:point1];
  210.     [list2 addObjectToList:point2];
  211.     [list2 addObjectToList:list1];/* lists can contatin lists */
  212.     printf("List 1\n");
  213.     [list1 print];
  214.     printf("List 2\n");
  215.     [list2 print];
  216.     exit(0);
  217. }
  218.  
  219. [LISTING THREE]
  220.  
  221. Turbo Pascal Implementation by Michael Floyd (Dr. Dobb's Journal) 
  222.  
  223. Program LListObj;
  224.  
  225. Type
  226.   PMyListData = ^MyListData;
  227.   MyListData = object
  228.      procedure Print; virtual;
  229.   end;
  230.   PMyListElement = ^MyListElement;
  231.   MyListElement = object
  232.     Data : PMyListData;
  233.     Next : PMyListElement;
  234.     constructor Init(initialData: PMyListData);
  235.   end;
  236.   PMyList = ^MyList;
  237.   MyList = object(MyListData)
  238.     Head, Tail: PMyListElement;
  239.     constructor Init;
  240.     procedure AddToList(var Data: PMyListData);
  241.     procedure Print; virtual;
  242.   end;
  243.    PMyNumber = ^MyNumber;
  244.    MyNumber = object(MyListData)
  245.       Value : Integer;
  246.       constructor Init(initialValue: Integer);
  247.       procedure Print; virtual;
  248.    end;
  249.    PMyPoint = ^MyPoint;
  250.    MyPoint = object(MyListData)
  251.       X, Y: Integer;
  252.       constructor Init(initialX, initialY: Integer);
  253.       procedure Print; virtual;
  254.    end;
  255. { MyListElement Methods }
  256. constructor MyListElement.Init(initialData: PMyListData);
  257. begin
  258.    data := initialData;
  259.    next := nil;
  260. end;
  261. { MyListData Methods }
  262. procedure MyListData.Print;
  263. begin
  264.    writeln('No Print Method!');
  265. end;
  266. { MyList Methods }
  267. constructor MyList.Init;
  268. begin
  269.    Head:= nil;
  270.    Tail:= nil;
  271. end;
  272. procedure MyList.AddToList(var Data: PMyListData);
  273. var
  274.   Added : PMyListElement;
  275. begin
  276.   Added := New(PMyListElement,Init(Data));
  277.   If Head = nil then
  278.   begin
  279.     Head := Added;
  280.     Tail := Added;
  281.   end
  282.   Else begin
  283.     Tail^.Next := Added;
  284.     Tail := Added;
  285.   end;
  286.   Added^.Next := nil;
  287. end;
  288. procedure MyList.Print;
  289. var
  290.    Current : PMyListElement;
  291. begin
  292.   Current := Head;
  293.   while Current <> nil do
  294.   begin
  295.       Current^.Data^.Print;
  296.       Current := Current^.Next;
  297.   end;
  298. end;
  299. { MyNumber Methods }
  300. constructor MyNumber.Init(initialValue: Integer);
  301. begin
  302.    Value := initialValue;
  303. end;
  304. procedure MyNumber.Print;
  305. begin
  306.    writeln('Number: ', Value);
  307. end;
  308. { MyPoint Methods }
  309. constructor MyPoint.Init(initialX, initialY: Integer);
  310. begin
  311.    X := initialX;
  312.    Y := initialY;
  313. end;
  314. procedure MyPoint.Print;
  315. begin
  316.    writeln('Point: ', X, ',',Y);
  317. end;
  318. { Main }
  319. Var
  320.    NumList, PointList : MyList;
  321.    Number, Coordinates: PMyListData;
  322.    I, J               : Integer;
  323. Begin
  324.    with NumList do begin      { create list of numbers }
  325.       Init;
  326.       For I := 1 to 5 do
  327.       begin
  328.         Number := New(PMyNumber, Init(I));
  329.         AddToList(Number);
  330.       end;
  331.       Print;
  332.    end;
  333.    with PointList do begin    { create list of points }
  334.       Init;
  335.       For I := 1 to 5 do
  336.       begin
  337.         J := I + 1;
  338.         Coordinates := New(PMyPoint, Init(I,J));
  339.         AddToList(Coordinates);
  340.       end;
  341.       Print;
  342.    end;
  343.    NumList.AddToList(Coordinates);    { Coords can be added to Number list }
  344.    NumList.Print;
  345.    readln;
  346. end.
  347.  
  348. [LISTING FOUR]
  349.  
  350. Parasol Implementation by Robert Jervis
  351.  
  352.  
  353. include file;
  354. /* any object that will appear in a list must inherit from this class */
  355. MyListData: type    { public:
  356. Print:  dynamic () = {
  357.     printf("No print method!\n");
  358.     }
  359. };
  360. MyList: public  type inherit MyListData {
  361.     head:   ref MyListElement;
  362.     tail:   ref MyListElement;
  363.     MyListElement:  type {
  364.     public:
  365.         data:   ref MyListData;
  366.         next:   ref MyListElement;
  367.     constructor:    (initialData: ref MyListData) = 
  368.                 { data = initialData; next = 0; }
  369.     };
  370. public:
  371. constructor:    () = { head = tail = 0; }
  372.  
  373. AddToList:  (data: ref MyListData) = {
  374.     newElement: ref MyListElement = new MyListElement[data];
  375.         if  (head == 0)
  376.                 head = tail = newElement;
  377.         else    {
  378.                 tail->next = newElement;
  379.                 tail = newElement;
  380.         }
  381.     }
  382. Print:  dynamic () = {
  383.     element:    ref MyListElement;
  384.     for (element = head; element != 0; element = element->next)
  385.         element->data Print();
  386.     }
  387. };
  388. MyNumber:   type    inherit MyListData {
  389.     value:  int;
  390. public:
  391. constructor:    (initialValue: int)  = { value = initialValue; }
  392. Print:  dynamic () = {
  393.     printf("Number: %d\n", value);
  394.     }
  395. };
  396. MyPoint:    type    inherit MyListData {
  397.     x:  int;
  398.     y:  int;
  399. public:
  400. constructor:   (initialX: int, initialY: int) = { x = initialX; y = initialY; }
  401. Print:  dynamic () = {
  402.     printf("Point: %d,%d\n", x, y);
  403.     }
  404. };
  405. main:   entry   () =
  406. {
  407.     list1:  ref MyList = new MyList[];
  408.     list2:  ref MyList = new MyList[];
  409.     n1: ref MyNumber = new MyNumber[10];
  410.     n2: ref MyNumber = new MyNumber[20];
  411.     p1: ref MyPoint = new MyPoint[2,3];
  412.     p2: ref MyPoint = new MyPoint[4,5];
  413.         /* build the lists */
  414.     list1 AddToList(n1);
  415.     list1 AddToList(n2);
  416.     list1 AddToList(p1);
  417.     list2 AddToList(n2);    /* an object can be in more than one list */
  418.     list2 AddToList(p1);    /*    at the same time                    */ 
  419.     list2 AddToList(p2);
  420.     list2 AddToList(list1); /* we can even put a list into another list */
  421.         /* print the lists */
  422.     printf("list1:\n");
  423.     list1 Print();
  424.     printf("list2:\n");
  425.     list2 Print();
  426. }
  427.  
  428. [LISTING FIVE]
  429.  
  430. C+@ Implementation by Jim Fleming (Unir Corp.)
  431.  
  432.  
  433. class MyListData {
  434.    method print
  435.    {
  436.        "No print method".print;
  437.    }
  438. }
  439. class MyListElement {
  440.    inherit MyListData;
  441.    MyListData    data;
  442.    MyListElement next;
  443.  
  444.    class method (_) new (initialData) {
  445.            _ = create
  446.            _.init(initialData);
  447.    }
  448.    method init (idata)  {
  449.        data = idata;
  450.        next = nil;
  451.    }
  452.    method (_) data {
  453.        _ = data;
  454.    }
  455.    method(_) next {
  456.        _ = next;
  457.    }
  458.    method linkTo (listElement) {
  459.        next = listElement;
  460.    }
  461. }
  462. class MyList {
  463.    MyListElement head;
  464.    MyListElement tail;
  465.   
  466.    class method (_) new {
  467.       _ = create;
  468.       _.init;
  469.    }
  470.    method init {
  471.       head = nil;
  472.       tail = nil;
  473.    } 
  474.    method addToList (data) {
  475.       var newElement;
  476.            newElement = MyListElement.new(data);
  477.            if(head == nil) { 
  478.               head = newElement;
  479.               tail = head;
  480.            }
  481.            else{
  482.               tail.linkTo(newElement);
  483.               tail = newELement;
  484.            }
  485.      }
  486.      method print {
  487.         var element;
  488.         for (element = head; element != nil; element = element.next) {
  489.            element.data.print;
  490.         }
  491.      }
  492. }
  493. class MyNumber {
  494.    Integer value;
  495.    class method (_) new (initialValue) {
  496.       _= create;
  497.        .init (initialValue)
  498.     }
  499.     method init (initialValue) {
  500.         value = initialValue;
  501.     }
  502.     method print  {
  503.        ("Number: " // value // "\n").print;
  504.     }
  505. }
  506. class MyPoint  {
  507.    Integer x;
  508.    Integer y;
  509.    class method (_) new (initialX,initialY) {
  510.       _= create;
  511.       .init(initialX,initialY);
  512.    }
  513.    method init (initialX,initialY) {
  514.       x = initialX;
  515.       y = initialY;
  516.     }
  517.     method print {
  518.       ("Point: "// x // "," // y // "\n").print
  519.     }
  520. }
  521. /* The following can be typed directly into command shell */
  522. list1 = Mylist.new;
  523. list2 = Mylist.new;
  524. n1 = Mynumber.new(10);
  525. n2 = Mynumber.new(20);
  526. p1 = MyPoint.new(2,3);
  527. p2 = MyPoint.new(4,5);
  528.  
  529. list1.addToList(n1);
  530. list1.addToList(n2);
  531. list1.addToList(p1);
  532. list2.addToList(n2); /* an object can be in more than one list */
  533. list2.addToList(p1);
  534. list2.addToList(p2);
  535. list2.addToList(list1); /* we can even put a list into another list */
  536. /* print the lists */
  537. "list1;\n".print;
  538. list1.print;
  539. "list2;\n".print;
  540. list2.print;
  541.  
  542.  
  543. [LISTING SIX]
  544.  
  545. Liana Implementation by Jack Krupansky (Base Technology)
  546.  
  547. class  MyList : array
  548. {
  549.            Print
  550.            {
  551.                   for (int i = 0, int n = size; i < n; i++)
  552.                        if ((any e = this [i]).isa ("MyList"))
  553.                                 e.Print();
  554.                        else
  555.                                 cout << e.class_name+": "+e.text+"\n";
  556.            }
  557. };
  558. //-------------------------------------------
  559. void main (void)
  560. {
  561.         MyList  list1 =   new   MyList;
  562.         MyList  list2 =   new   MyList;
  563.         int     n1 =      10;
  564.         int     n2 =      20;
  565.         point   p1 =      new   point (2,3);
  566.         point   p2 =      new   point (4,5);
  567.  
  568.         /* build the lists */
  569.         list1 << n1 << n2 << p1;
  570.  
  571.         /* an obj can be in more than one lst at same time */
  572.         list2 << n2 << p1 << p2;
  573.  
  574.         list2 << list1; /* we can even put a list into another list  */
  575.  
  576.         /* print the lists */
  577.         cout << "\nLIST1:\n";    list1.Print;
  578.         cout << "\nLIST2:\n";    list2.Print;
  579. }
  580.  
  581. [LISTING SEVEN]
  582.  
  583. Minimal Smalltalk implementation by Ray Valdes (Dr. Dobb's Journal)
  584.  
  585. OrderedCollection subclass: #MyListClass
  586.   instanceVariableNames: ''
  587.   classVariableNames: ''
  588.   poolDictionaries: ''   !
  589. !MyListClass class methods ! !
  590. !MyListClass methods !
  591. printOn: aStream
  592.     " Method to display list elements, recursing if necessary "
  593.     aStream cr; nextPutAll:  ' ',(self class name),' '; cr.
  594.     self do: [:c | c printOn: aStream. aStream cr ].
  595.     ^self. 
  596. !
  597. test
  598.     " Program to test the linked-list class "
  599.     | 
  600.        aList1 aList2 aNumber1 aNumber2 aPoint1 aPoint2 aMsg 
  601.     |
  602.     aList1 := MyListClass new. 
  603.     aList2 := MyListClass new. 
  604.     aNumber1 := 10.                  
  605.     aNumber2 := 20.
  606.     aPoint1 := (2 @ 3).
  607.     aPoint2 := (4 @ 5).
  608.     " build the lists "
  609.     aList1 add: aNumber1; add: aNumber2; add: aPoint1.
  610.     " an object can be in more than one list at same time "
  611.     aList2 add: aNumber2; add: aPoint1;      add: aPoint2.
  612.     " we can even put a list into another list "
  613.     aList2 add: aList1.
  614.     " print the lists "
  615.     aList1 printOn: Transcript.
  616.     aList2 printOn: Transcript.
  617. ! !
  618.  
  619.  
  620. [LISTING EIGHT]
  621.  
  622. Complete Smalltalk/V implementation by Ray Valdes (Dr. Dobb's Journal)
  623.  
  624. "-------------------------------------------------------------"
  625. Object subclass: #MyListClasses
  626.   instanceVariableNames: ''
  627.   classVariableNames: ''
  628.   poolDictionaries: ''    !
  629. !MyListClasses class methods ! !
  630. !MyListClasses methods ! !
  631. "-------------------------------------------------------------"
  632. MyListClasses subclass: #TestList
  633.   instanceVariableNames: ''
  634.   classVariableNames: ''
  635.   poolDictionaries: ''    !
  636. !TestList class methods ! !
  637. !TestList methods ! 
  638. test
  639.     " Program to test the linked-list class "
  640.     | 
  641.        aList1 aList2 aNumber1 aNumber2 aPoint1 aPoint2 
  642.     |
  643.     aList1   := MyList new. 
  644.     aList2   := MyList new. 
  645.     aNumber1 := MyNumber new: 10.                  
  646.     aNumber2 := MyNumber new: 20.
  647.     aPoint1  := MyPoint  new: (2 @ 3).
  648.     aPoint2  := MyPoint  new: (4 @ 5).
  649.     " build the lists "
  650.     aList1 add: aNumber1; add: aNumber2; add: aPoint1.
  651.     " an object can be in more than one list at same time "
  652.     aList2 add: aNumber2; add: aPoint1;      add: aPoint2.
  653.     " we can even put a list into another list "
  654.     aList2 add: aList1.
  655.     " print the lists "
  656.     aList1 print.
  657.     aList2 print! !
  658. "------------------------------------------------------------------"
  659. MyListClasses subclass: #MyListElement
  660.   instanceVariableNames: 'data next'
  661.   classVariableNames: ''
  662.   poolDictionaries: ''    !
  663. !MyListElement class methods ! 
  664. new: someData
  665.    ^super new initialize: someData! !
  666. !MyListElement methods ! 
  667. initialize: someData
  668.      data := someData.
  669.      ^self! 
  670. next
  671.     ^next!
  672. next: anElement
  673.       next := anElement.
  674.       ^self! 
  675. print
  676.       data print.
  677.       ^self! !
  678. "-------------------------------------------------------------"
  679. MyListClasses subclass: #MyListData
  680.   instanceVariableNames: ''
  681.   classVariableNames: ''
  682.   poolDictionaries: ''    !
  683. !MyListData class methods ! !
  684. !MyListData methods ! 
  685. print
  686.    Transcript cr; nextPutAll: 'Must override this method'; cr.
  687.    ^self! !
  688. "-------------------------------------------------------------"
  689. MyListData subclass: #MyList
  690.   instanceVariableNames: 'head tail'
  691.   classVariableNames: ''
  692.   poolDictionaries: ''  !
  693. !MyList class methods ! !
  694. !MyList methods !
  695. add: someData
  696.     | anElement |
  697.     anElement := MyListElement new: someData.
  698.     head isNil
  699.       ifTrue:  [ head := anElement. tail := anElement ]
  700.       ifFalse: [ tail next: anElement.  tail := anElement].
  701.      ^self! 
  702. print
  703.     | anElement | 
  704.     anElement := head.
  705.     [anElement isNil] 
  706.     whileFalse: [ 
  707.         anElement print.
  708.         anElement := anElement next .
  709.         Transcript cr.
  710.         ].
  711.      ^self! !
  712. "-------------------------------------------------------------"
  713. MyListData subclass: #MyNumber
  714.   instanceVariableNames: 'value'
  715.   classVariableNames: ''
  716.   poolDictionaries: ''    !
  717. !MyNumber class methods !
  718. new: aValue
  719.     ^super new initialize: aValue! !
  720. !MyNumber methods !
  721. initialize: aValue
  722.      value := aValue.
  723.      ^self! 
  724. print
  725.     value printOn: Transcript.
  726.     ^self! !    
  727. "-------------------------------------------------------------"
  728. MyListData subclass: #MyPoint
  729.   instanceVariableNames: 'point'
  730.   classVariableNames: ''
  731.   poolDictionaries: '' !
  732. !MyPoint class methods ! 
  733. new: aPoint
  734.     ^super new initialize: aPoint! !
  735. !MyPoint methods ! 
  736. initialize: aPoint
  737.     point := aPoint.
  738.     ^self!
  739. print
  740.     point printOn: Transcript.
  741.     ^self! !    
  742.  
  743.  
  744. [LISTING NINE]
  745.  
  746. Eiffel Implementation by Robert Howard (Tower Technology)
  747.  
  748.  
  749. class DRIVER
  750.    -- In Eiffel, the top level driver is an object, too.
  751. inherit
  752.    BASIC_IO
  753. creation
  754.    make
  755. feature {ANY}
  756.    make is
  757.      -- run this test driver
  758.       local
  759.      list1, list2 : MY_LIST[PRINTABLE] ;
  760.      n1, n2 : MY_NUMBER ; -- a kind of PRINTABLE
  761.      p1, p2 : MY_POINT ;  -- also a kinf of PRINTABLE
  762.       do
  763.          -- create the various objects
  764.      !!list1 ;
  765.      !!list2 ;
  766.      !!n1.set( 10 ) ;
  767.      !!n2.set( 20 ) ;
  768.      !!p1.set( 2, 3 ) ;
  769.      !!p2.set( 4, 5 ) ;
  770.      
  771.      list1.add_to_list( n1 ) ;
  772.      list1.add_to_list( n2 ) ;
  773.      list1.add_to_list( p1 ) ;
  774.      list2.add_to_list( n2 ) ; -- objects can be in more than one list
  775.      list2.add_to_list( p1 ) ;
  776.      list2.add_to_list( p2 ) ;
  777.      list2.add_to_list( list1 ) ; -- list 1 is an element of list 2
  778.      
  779.      put_string( "list1:%N" ) ;
  780.      list1.print_self ;
  781.      put_string( "list2:%N" ) ;
  782.      list2.print_self ;
  783.       end -- make
  784. end -- DRIVER
  785. deferred class PRINTABLE
  786.    -- insures that 'print_self' is implemented
  787. inherit
  788.    BASIC_IO
  789. feature {ANY}
  790.    print_self is
  791.      -- print yourself
  792.       deferred
  793.       end -- print_self
  794. end -- PRINTABLE
  795. class MY_NUMBER
  796.    -- holds and can print an integer
  797. inherit
  798.    PRINTABLE
  799. creation
  800.    set
  801. feature {ANY}
  802.  
  803.    value : INTEGER ;
  804.    set( new_value : INTEGER ) is
  805.      -- set this number
  806.       do
  807.      value := new_value ;
  808.       end ; -- make
  809.    print_self is
  810.      -- print the value
  811.       do
  812.      put_string( "Number: " ) ;
  813.      put_int( value ) ;
  814.      put_newline ;
  815.       end ; -- print_self
  816. end -- MY_NUMBER
  817. class MY_POINT
  818.    -- holds and can print an x,y pair
  819. inherit
  820.    PRINTABLE
  821. creation
  822.    set
  823. feature {ANY}
  824.    x, y : INTEGER ;
  825.    set( new_x : INTEGER; new_y : INTEGER ) is
  826.      -- set this point
  827.       do
  828.      x := new_x ;
  829.      y := new_y
  830.       end ; -- set
  831.    print_self is
  832.      -- print the value
  833.       do
  834.      put_string( "Point: " ) ;
  835.      put_int( x ) ;
  836.      put_char( ',' ) ;
  837.      put_int( y ) ;
  838.      put_newline ;
  839.       end ; -- print_self
  840. end -- MY_POINT
  841. class ELEMENT[T]
  842.    -- holds an object reference and a
  843.    -- single link to another ELEMENT[T]
  844. creation
  845.    set_data
  846. feature {LIST}
  847.    data : T ;
  848.    next : ELEMENT[T] ;
  849.    set_data( new_data : T ) is
  850.      -- set data to the new_data
  851.       do
  852.      data := new_data
  853.       end ; -- set_data
  854.    set_next( new_next : ELEMENT[T] ) is
  855.      -- set next to the element
  856.       do
  857.      next := new_next
  858.  
  859.       end ; -- set_next
  860. end -- class ELEMENT
  861. class LIST[T]
  862.    -- a generic linked list class
  863. feature {ANY}
  864.    add_to_list( data : T ) is
  865.      -- add to the end of the list
  866.       local
  867.      new_element : ELEMENT[T] ;
  868.       do
  869.      !!new_element.set_data( data ) ;
  870.      if head = void
  871.       then
  872.         head := new_element ;
  873.      else
  874.         tail.set_next( new_element ) ;
  875.      end
  876.      tail := new_element ;
  877.       end ; -- add_to_list
  878. feature {NONE}
  879.    head, tail : ELEMENT[T] ;
  880. invariant
  881.    tail_next_is_void: tail.next = void ;
  882.    tail_void_when_head_void: head = void implies tail = void
  883. end -- LIST
  884. class MY_LIST[T->PRINTABLE]
  885.    -- A printable list which holds printable data
  886. inherit
  887.    LIST[T]
  888.    PRINTABLE
  889. feature {ANY}
  890.    print_self is
  891.      -- print the list elements
  892.       local
  893.      el : ELEMENT[T] ;
  894.       do
  895.      from
  896.         el := head
  897.      until
  898.         el = void
  899.      loop
  900.         el.data.print_self
  901.         el := el.next ;
  902.      end ;
  903.       end ; -- print_self
  904. end -- MY_LIST
  905.  
  906.  
  907. [LISTING TEN] 
  908.  
  909. Sather Implementation by Stephen Omhundro (ICSI)
  910.  
  911. -------------------------------------------------------------------
  912. abstract class $MY_LIST_DATA is
  913.    -- Data that will appear in a list must inherit this class.
  914.    
  915.    print is
  916.       -- Print the data on OUT. Should be redefined in descendants.
  917.       #OUT + "No print routine defined!\n" end;
  918. end;
  919. -------------------------------------------------------------------
  920. class MY_LIST_ELEMENT is
  921.    -- An element of a MY_LIST.
  922.    
  923.    attr data:$MY_LIST_DATA;
  924.    attr next:MY_LIST_ELEMENT;
  925. end;
  926. -------------------------------------------------------------------
  927. class MY_LIST is
  928.    -- A double ended linked list.
  929.    inherit $MY_LIST_DATA;
  930.    
  931.    private head, tail:MY_LIST_ELEMENT;
  932.    
  933.    add_to_list($MY_LIST_DATA) is
  934.       -- Append arg to the end of self.
  935.       new_elt::=#MY_LIST_ELEMENT(data:=arg);
  936.       if head=void then head:=new_elt
  937.       else tail.next:=new_elt end; 
  938.       tail:=new_elt end;
  939.    
  940.    print is
  941.       -- Print the data held in the list on OUT.
  942.       elt::=head;      
  943.       loop while!(elt/=void); elt.data.print; 
  944.      elt:=elt.next end end;
  945. end;
  946. -------------------------------------------------------------------
  947. class MY_NUMBER is
  948.    -- An integer value that can be held in a MY_LIST.
  949.    inherit $MY_LIST_DATA;
  950.  
  951.    attr value:INT;
  952.    
  953.    print is
  954.       -- Print the integer value on OUT.
  955.       #OUT + "Number: " + value + "\n" end;
  956. end;
  957. -------------------------------------------------------------------
  958. class MY_POINT is
  959.    -- A two-dimensional point that can be held in a MY_LIST.
  960.    inherit $MY_LIST_DATA;
  961.    
  962.    attr x,y:INT;
  963.    
  964.    print is
  965.       -- Print the point coordinates on OUT.
  966.       #OUT + "Point: " + x + "," + y + "\n" end;
  967. end;
  968. -------------------------------------------------------------------
  969. class MY_LIST_TEST is
  970.    -- Test of MY_LIST.
  971.    
  972.    main is
  973.       -- Add some numbers and points to lists and print them out.
  974.       list1::=#MY_LIST; list2::=#MY_LIST; 
  975.       n1::=#MY_NUMBER(10); n2::=#MY_NUMBER(20);
  976.       p1::=#MY_POINT(2,3); p2::=#MY_POINT(4,5);
  977.       -- Build the lists:
  978.       list1.add_to_list(n1); list1.add_to_list(n2); 
  979.       list1.add_to_list(p1); 
  980.       list2.add_to_list(n2);    -- An object can be in more than one list.
  981.       list2.add_to_list(p1); list2.add_to_list(p2);
  982.       list2.add_to_list(list1); -- Put a list in another list.
  983.        -- Print the lists
  984.       #OUT + "list1:\n";
  985.       list1.print;
  986.       #OUT + "list2:\n";
  987.       list2.print end;
  988. end;
  989.  
  990.  
  991. [LISTING ELEVEN]
  992.  
  993. Beta Implementation by Steve Mann (MADA)
  994.  
  995. --- program:descriptor---
  996. (#
  997.    MyListData: (#  Print:< (# do INNER #)  #);
  998.    MyListElement: (#   data: ^MyListData;  next: ^MyListElement;   #);
  999.    MyList: MyListData (#
  1000.        head, tail: ^MyListElement;
  1001.    AddToList: (#
  1002.        newItem: ^MyListData
  1003.        enter newItem[]
  1004.        do  (if head[] = NONE // TRUE then
  1005.            &MyListElement[] -> head[] -> tail[];
  1006.            newItem[] -> head.data[];
  1007.           else
  1008.            &MyListElement[]-> tail.next[] -> tail[];
  1009.            newItem[] -> tail.data[];
  1010.           if);
  1011.    #);
  1012.    Print::< (#
  1013.        element: ^MyListElement
  1014.        do head[] -> element[];
  1015.            loop    (# while::< (# do element[] <> NONE -> value #);
  1016.        do  element.data.print; element.next[] -> element[];
  1017.    #); #); #);
  1018.    MyNumber: MyListData (#
  1019.    value: @integer;
  1020.         Print::< (# do 'Number: ' -> PutText; value -> PutInt; NewLine; #);
  1021.         enter value
  1022.     #);
  1023.    MyPoint: MyListData (#
  1024.    x, y: @integer;
  1025.         Print::< (# do  'Point: ' -> PutText;   x -> PutInt;
  1026.         ', ' -> PutText;    y -> PutInt;NewLine;
  1027.      #);
  1028.      enter (x, y)
  1029.      #);
  1030. (********************** MAIN **************************)
  1031.    list1, list2: @MyList;
  1032.    n1, n2: @MyNumber;  p1, p2: @MyPoint;
  1033. do
  1034.    10 -> n1;   20 -> n2;
  1035.    (2, 3) -> p1;   (4, 5) -> p2;
  1036.  
  1037.    n1[] -> list1.AddToList;n2[] -> list1.AddToList;
  1038.    p1[] -> list1.AddToList;
  1039.  
  1040.    n2[] -> list2.AddToList;p1[] -> list2.AddToList;
  1041.    p2[] -> list2.AddToList;list1[] -> list2.AddToList;
  1042.  
  1043.    'list1: ' -> PutLine;   list1.Print;
  1044.    'list2: ' -> PutLine;   list2.Print;
  1045. #)
  1046.  
  1047.  
  1048. [LISTING TWELVE] 
  1049.  
  1050. Drool Implementation by David Betz (Dr. Dobb's Journal)
  1051.  
  1052.  
  1053. (defobject MyListElement ()
  1054.   (property next nil
  1055.             data nil))
  1056. (defobject MyList ()
  1057.   (property head nil
  1058.             tail nil))
  1059. (defmethod (MyList 'AddToList data)
  1060.   (let ((newElement (clone MyListElement 'data data))
  1061.         (tail (getp self 'tail)))
  1062.     (if tail
  1063.       (setp! tail 'next newElement)
  1064.       (setp! self 'head newElement))
  1065.     (setp! self 'tail newElement)))
  1066. (defmethod (MyList 'Print)
  1067.   (let ((element (getp self 'head)))
  1068.     (while element
  1069.       ((getp element 'data) 'Print)
  1070.       (set! element (getp element 'next)))))
  1071. (defobject MyNumber ()
  1072.   (property value 0))
  1073. (defmethod (MyNumber 'Print)
  1074.   (print "Number: " (getp self 'value) "\n"))
  1075. (defobject MyPoint ()
  1076.   (property x 0
  1077.             y 0))
  1078. (defmethod (MyPoint 'Print)
  1079.   (print "Point: " (getp self 'x) "," (getp self 'y) "\n"))
  1080. (define (main)
  1081.   (let ((list1 (clone MyList))
  1082.         (list2 (clone MyList))
  1083.         (n1 (clone MyNumber 'value 10))
  1084.         (n2 (clone MyNumber 'value 20))
  1085.         (p1 (clone MyPoint 'x 2 'y 3))
  1086.         (p2 (clone MyPoint 'x 4 'y 5)))
  1087.     (list1 'AddToList n1)
  1088.     (list1 'AddToList n2)
  1089.     (list1 'AddToList p1)
  1090.     (list2 'AddToList n2)
  1091.     (list2 'AddToList p1)
  1092.     (list2 'AddToList p2)
  1093.     (list2 'AddToList list1)
  1094.     (print "list1\n")
  1095.     (list1 'Print)
  1096.     (print "list2\n")
  1097.     (list2 'Print)))
  1098.  
  1099.  
  1100. [LISTING THIRTEEN]
  1101.  
  1102. Ada Implementation by Mike Ruf (Rational)
  1103.  
  1104. -- Ada83 does not support run-time polymorphism, so only supports homogeneous
  1105. -- lists. Ada9X will run-time polymorphism. There are ways to simulate run-time
  1106. -- polymorphism in Ada83, which is discussed in: Seidewitz, Ed, 
  1107. -- "Object-Oriented Programming Through Type Extension in Ada 9X," Ada 
  1108. -- Letters, Volume 11, Number 2, Mar/Apr 1991, pages 86-97. Hirasuna, Michael,
  1109. -- "Using Inheritance and Polymorphism with Ada in Government Sponsored 
  1110. -- Contracts", Ada Letters, Volume 12, Number 2, Mar/Apr, 1992, pp. 43-56.
  1111. -- Mike Ruf, Rational Systems
  1112. -- This package implements a singly-linked list abstraction.
  1113. --
  1114. generic
  1115.     type Element is private;
  1116.     with procedure Print (This : Element);
  1117. package Printable_List_Generic is
  1118.     type List is private;
  1119.     function New_List return List;
  1120.     -- Returns an empty list.
  1121.     procedure Append (To_List : in out List;
  1122.                       This_Element : in Element);
  1123.     -- Propagates the Storage_Error exception if it occurs.
  1124.     procedure Print (This : in List);
  1125.     -- For each element in the list, calls the Print procedure,
  1126.     -- which is supplied as a generic formal parameter.
  1127. private
  1128.     type Node;
  1129.     type Pointer is access Node;
  1130.     type Node is
  1131.         record
  1132.             Contents : Element;
  1133.             Next : Pointer := null;
  1134.         end record;
  1135.     type List is
  1136.         record
  1137.             First : Pointer := null;
  1138.             Last : Pointer := null;
  1139.         end record;
  1140. end Printable_List_Generic;
  1141. package body Printable_List_Generic is
  1142.     function New_List return List is
  1143.     begin
  1144.         return (List'(First => null, Last => null));
  1145.     end New_List;
  1146.     procedure Append (To_List : in out List;
  1147.                       This_Element : in Element) is
  1148.        New_Node : Pointer := new Node'(Contents => This_Element, Next => null);
  1149.        -- The "next" component of the last node is always "null"
  1150.     begin
  1151.         if To_List.First = null then
  1152.             To_List.First := New_Node;
  1153.             To_List.Last := New_Node;
  1154.         else
  1155.             To_List.Last.Next := New_Node;
  1156.             To_List.Last := New_Node;
  1157.         end if;
  1158.     end Append;
  1159.     procedure Print (This : in List) is
  1160.         Current : Pointer := This.First;
  1161.     begin
  1162.         while (not (Current = null)) loop
  1163.             Print (Current.Contents);
  1164.             Current := Current.Next;
  1165.         end loop;
  1166.     end Print;
  1167. end Printable_List_Generic;
  1168.  
  1169. package Geometry is
  1170.     type Number is new Integer;
  1171.     procedure Print (This : Number);
  1172.     type Point is
  1173.         record
  1174.             X : Number := 0;
  1175.             Y : Number := 0;
  1176.         end record;
  1177.     procedure Print (This : Point);
  1178. end Geometry;
  1179.  
  1180. package body Geometry is
  1181.     procedure Print (This : Number) is
  1182.     begin
  1183.         Text_Io.Put_Line ("Number:" & Number'Image (This));
  1184.     end Print;
  1185.     procedure Print (This : Point) is
  1186.     begin
  1187.         Text_Io.Put_Line ("Point: " & Number'Image (This.X) &
  1188.                           "," & Number'Image (This.Y));
  1189.     end Print;
  1190. end Geometry;
  1191.  
  1192. procedure List_Example;
  1193.  
  1194. with Geometry;
  1195. with Printable_List_Generic;
  1196.  
  1197. procedure List_Example is
  1198.     package Numbers is new Printable_List_Generic (Element => Geometry.Number,
  1199.                                                    Print => Geometry.Print);
  1200.     package Points is new Printable_List_Generic (Element => Geometry.Point,
  1201.                                                   Print => Geometry.Print);
  1202.     Number_List : Numbers.List := Numbers.New_List;
  1203.     Point_List : Points.List := Points.New_List;
  1204.     N1 : Geometry.Number := 10;
  1205.     N2 : Geometry.Number := 20;
  1206.     P1 : Geometry.Point := (2, 3);
  1207.     P2 : Geometry.Point := (4, 5);
  1208. begin
  1209.     -- Build the lists
  1210.     Numbers.Append (To_List => Number_List, This_Element => N1);
  1211.     Numbers.Append (To_List => Number_List, This_Element => N2);
  1212.     --
  1213.     Points.Append (To_List => Point_List, This_Element => P1);
  1214.     Points.Append (To_List => Point_List, This_Element => P2);
  1215.     -- Print the lists
  1216.     Numbers.Print (Number_List);
  1217.     Points.Print (Point_List);
  1218. end List_Example;
  1219.  
  1220. ------------------------------- OUTPUT  -------------------------------
  1221. Number: 10
  1222. Number: 20
  1223. Point:  2, 3
  1224. Point:  4, 5
  1225.  
  1226.  
  1227.